package org.rc.six;

import com.google.appengine.api.memcache.stdimpl.GCacheFactory;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
import javax.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author dokeeffe
 */
public class SearchService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SearchService.class);
    private static final String CACHE_KEY = "SEARCH_RESULTS_";
    private IndexDao indexDao;
    protected Cache resultsCache;

    /**
     * Constructor
     */
    public SearchService() {
        Map props = new HashMap();
        props.put(GCacheFactory.EXPIRATION_DELTA, 7200);
        try {
            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
            resultsCache = cacheFactory.createCache(props);
        } catch (CacheException e) {
            LOGGER.error("error setting up cache",e);
        }
        if(indexDao==null) {
            indexDao= new DataStoreIndexDao(); //default this one. FIXME: a factory or some DI wiring needed
        }
    }

    /**
     * An auto complete style search. returns a set that match the string passed as a radix
     * Example "pa" will return "patrick" "partial" etc
     * Returns a Set of json strings representing {@link Document} s
     *
     * @param query
     * @return
     */
    public Set<String> autoCompleteSearch(String query) {
        Set<String> result = new LinkedHashSet<String>();
        Set<String> terms = new HashSet<String>(Arrays.asList(query.toLowerCase().split(" ")));
        for (String term : terms) {
            if (term.length() > 1) {
                Set<String> res = indexDao.getIndex(term).lookupTermRadix(term);
                if (res != null && !res.isEmpty()) {
                    if (result.isEmpty()) {
                        result.addAll(res);
                    } else {
                        result.retainAll(res);
                    }
                }
            }
        }
        return result;
    }

    /**
     * Returns a Set of json strings representing {@link Document} s
     * @param query
     * @return
     */
    public Set<String> termSearch(String query) {
        LOGGER.debug("searching for:" +query);
        Set<String> result = new LinkedHashSet<String>();
        if(resultsCache.get(CACHE_KEY+query)!=null) {
            LOGGER.debug("cache hit for search");
            result =  (Set<String>) resultsCache.get(CACHE_KEY+query);
        } else {

            Set<String> terms = new HashSet<String>(Arrays.asList(query.toLowerCase().split(" ")));
            for (String term : terms) {
                if (term.length() > 1) {
                    Set<String> res = indexDao.getIndex(term).lookupTermRadix(term);
                    if (res != null && !res.isEmpty()) {
                        if (result.isEmpty()) {
                            result.addAll(res);
                        } else {
                            result.retainAll(res);
                        }
                    }
                }
            }
            LOGGER.debug("putting result in cache: " + CACHE_KEY+query);
            resultsCache.put(CACHE_KEY+query, result);
        }
        return result;
    }
    /**
     * @param indexWriter the indexStore to set
     */
    public void setIndexWriter(IndexDao indexWriter) {
        this.indexDao = indexWriter;
    }
}
